/*
 * File Name: ProtoField.h
 *
 * Created on: 2021-01-28
 * Author: glendy ganby@163.com
 *
 * Last Modified: 2021-01-28
 * Description:
 */

#ifndef _PROTOFIELD_H_
#define _PROTOFIELD_H_

#include <string>
#include <vector>
#include <stdint.h>

namespace miniproto
{
class ProtoBaseField;
class Message;
class BufferStream;

class ProtoField
{
public:
	typedef ::std::vector<bool> BoolList;
	typedef ::std::vector<int32_t> Int32List;
	typedef ::std::vector<int64_t> Int64List;
	typedef ::std::vector<uint32_t> UInt32List;
	typedef ::std::vector<uint64_t> UInt64List;
	typedef ::std::vector<float> FloatList;
	typedef ::std::vector<double> DoubleList;
	typedef ::std::vector< ::std::string * > StringList;
	typedef ::std::vector< ::miniproto::Message * > MessageList;

public:
	ProtoField();
	~ProtoField();

	int ByteSize(const uint32_t number) const;
	void Clear();
	void set_field_set(const bool val);
	bool is_field_set() const;
	int field_size() const;
	uint8_t field_type() const;

	void init_field_bool(bool *point);
	void init_field_int32(int32_t *point);
	void init_field_int64(int64_t *point);
	void init_field_uint32(uint32_t *point);
	void init_field_uint64(uint64_t *point);
	void init_field_float(float *point);
	void init_field_double(double *point);
	void init_field_string(::std::string *point);
	void init_field_bytes(::std::string *point);
	void init_field_message(::miniproto::Message *point);

	void init_field_bool_list(BoolList *point);
	void init_field_int32_list(Int32List *point);
	void init_field_int64_list(Int64List *point);
	void init_field_uint32_list(UInt32List *point);
	void init_field_uint64_list(UInt64List *point);
	void init_field_float_list(FloatList *point);
	void init_field_double_list(DoubleList *point);
	void init_field_string_list(StringList *point);
	void init_field_bytes_list(StringList *point);
	void init_field_message_list(MessageList *point);

	void set_field_bool(const bool val);
	void set_field_int32(const int32_t val);
	void set_field_int64(const int64_t val);
	void set_field_uint32(const uint32_t val);
	void set_field_uint64(const uint64_t val);
	void set_field_float(const float val);
	void set_field_double(const double val);
	void set_field_string(::std::string *val);
	void set_field_message(::miniproto::Message *val);

	void add_field_bool(const bool val);
	void add_field_int32(const int32_t val);
	void add_field_int64(const int64_t val);
	void add_field_uint32(const uint32_t val);
	void add_field_uint64(const uint64_t val);
	void add_field_float(const float val);
	void add_field_double(const double val);
	void add_field_string(::std::string *val);
	void add_field_message(::miniproto::Message *val);

	bool get_field_bool() const;
	int32_t get_field_int32() const;
	int64_t get_field_int64() const;
	uint32_t get_field_uint32() const;
	uint64_t get_field_uint64() const;
	float get_field_float() const;
	double get_field_double() const;
	::std::string *get_field_string();
	::miniproto::Message *get_field_message();
	const ::std::string *get_field_string() const;
	const ::miniproto::Message *get_field_message() const;

	const BoolList *get_field_bool_list() const;
	const Int32List *get_field_int32_list() const;
	const Int64List *get_field_int64_list() const;
	const UInt32List *get_field_uint32_list() const;
	const UInt64List *get_field_uint64_list() const;
	const FloatList *get_field_float_list() const;
	const DoubleList *get_field_double_list() const;
	const StringList *get_field_string_list() const;
	const MessageList *get_field_message_list() const;

	void copy(const ProtoField &field);

private:
	int bool_byte_size(const bool *val) const;
	int bool_byte_size(const BoolList *list) const;
	int int32_byte_size(const int32_t *val) const;
	int int32_byte_size(const Int32List *list) const;
	int uint32_byte_size(const uint32_t *val) const;
	int uint32_byte_size(const UInt32List *list) const;
	int int64_byte_size(const int64_t *val) const;
	int int64_byte_size(const Int64List *list) const;
	int uint64_byte_size(const uint64_t *val) const;
	int uint64_byte_size(const UInt64List *list) const;
	int float_byte_size(const float *val) const;
	int float_byte_size(const FloatList *list) const;
	int double_byte_size(const double *val) const;
	int double_byte_size(const DoubleList *list) const;
	int string_byte_size(const std::string *val) const;
	int string_byte_size(const StringList *list) const;
	int message_byte_size(const ::miniproto::Message *val) const;
	int message_byte_size(const MessageList *list) const;

private:
	bool field_set_;	// 字段设置标志, true已设置
	uint8_t type_;
	union{
		bool *bool_val_;
		int32_t *int32_val_;
		int64_t *int64_val_;
		uint32_t *uint32_val_;
		uint64_t *uint64_val_;
		float *float_val_;
		double *double_val_;
		::std::string *string_val_;
		::miniproto::Message *message_val_;

		BoolList *bool_list_;
		Int32List *int32_list_;
		Int64List *int64_list_;
		UInt32List *uint32_list_;
		UInt64List *uint64_list_;
		FloatList *float_list_;
		DoubleList *double_list_;
		StringList *string_list_;
		MessageList *message_list_;
	};
};

} // namespace miniproto

#endif //_PROTOFIELD_H_
